package entity

import (
	"bytes"
	"fmt"
	"strings"
	"time"

	"gorm.io/gorm"
	"shqsoft.cn/pas3ui/base"
)

//业绩转移
type UserChangeDivi struct {
	ID           int       `gorm:"AUTO_INCREMENT;primary_key;column:ID"`
	YEMID        int       `gorm:"column:YEMID"`
	User         User      `gorm:"ForeignKey:YEMID"`
	NEMID        int       `gorm:"column:NEMID"`
	User1        User      `gorm:"ForeignKey:NEMID"`
	DSDT         time.Time `gorm:"column:DSDT"`
	CZRQ         time.Time `gorm:"column:CZRQ"`
	ZYFS         string    `gorm:"column:ZYFS"`
	ZYFSCaptions string    `gorm:"-"`
}

//TableName 业绩转移
func (UserChangeDivi) TableName() string {
	return "T_USER_DIVI_CHANGE"
}

func (i *UserChangeDivi) BeforeSave(tx *gorm.DB) (err error) {
	i.CZRQ = time.Now()
	bdate, err := base.GetBackDATE()
	if err != nil {
		return
	}
	if i.DSDT.Unix() < bdate.Unix() {
		err = fmt.Errorf("分户日期不能小于最早可追溯日期，最大追溯日期为【" + bdate.Format("2006-01-02") + "】")
		return
	}
	eng := "ENGINE=MEMORY DEFAULT CHARSET=utf8"
	if base.AppConf.Database.Mysql == "" {
		eng = ""
	}
	dgtps := make([]string, 0, 2)
	if strings.Contains(i.ZYFS, "1") {
		dgtps = append(dgtps, "1")
	}
	if strings.Contains(i.ZYFS, "2") {
		dgtps = append(dgtps, "2")
		dgtps = append(dgtps, "81")
		dgtps = append(dgtps, "82")
		dgtps = append(dgtps, "83")
	}
	if len(dgtps) > 0 {
		//创建内存表
		sqlstr := fmt.Sprintf(`CREATE TABLE "TMP_DGCDK"(
			"ACID" int,
			"DSTY" int,
			"EMID" int,
			"DSVL" decimal(16,4),
			"DSDT" date,
			"WODT" date,
			"ISWO" int,
			"DSEM" varchar(20),
			"WOEM" varchar(20)
		)%s`, eng)
		err = base.MYDB.Exec(sqlstr).Error
		if err != nil {
			return
		}
		//插入对公业绩转移(未终止)
		sqlstr = `INSERT INTO mysql."TMP_DGCDK"("ACID","DSTY","EMID","DSVL","DSDT","WODT","ISWO","DSEM","WOEM")
				WITH dictGetUInt8('DICT_ITEM','FPNO',toUInt64(B.ITID)) AS FPNO
		SELECT "ACID","DSTY",?,"DSVL","DSDT","WODT","ISWO",'YJZY' "DSEM","WOEM"
		FROM mysql."T_COMP_ACCO_DIVI" A INNER JOIN "T_COMP_ACCO" B ON toUInt64(A."ACID") = B."ID"
		WHERE "EMID"=? AND A."ISWO"=0 AND ("WODT" IS NULL OR "WODT">?) AND FPNO IN (?)`
		err = base.CHDB.Exec(sqlstr, i.NEMID, i.YEMID, i.DSDT, dgtps).Error
		if err != nil {
			tx.Rollback()
			return
		}
		//终止认定
		sqlstr = `UPDATE "T_COMP_ACCO_DIVI" SET "WODT"=?,"WOEM"='YJZY',"ISWO"=CASE WHEN "DSDT"<? THEN 0 ELSE 1 END
		WHERE "EMID"=? AND "ISWO"=0 AND ("WODT" IS NULL OR "WODT">?) AND "ACID" in (select "ACID" from "TMP_DGCDK")`
		err = tx.Exec(sqlstr, i.DSDT, i.DSDT, i.YEMID, i.DSDT).Error
		if err != nil {
			tx.Rollback()
			return
		}
		//插入认定
		sqlstr = `INSERT INTO "T_COMP_ACCO_DIVI"("ACID","DSTY","EMID","DSVL","DSDT","DSEM","WODT","WOEM","ISWO")
		SELECT "ACID","DSTY","EMID","DSVL",
				CASE WHEN "DSDT"<? THEN ? ELSE "DSDT" END "DSDT",
				"DSEM","WODT","WOEM","ISWO"
		FROM "TMP_DGCDK"
		WHERE "DSDT"<"WODT" OR "WODT" IS NULL`
		err = tx.Exec(sqlstr, i.DSDT, i.DSDT).Error
		if err != nil {
			tx.Rollback()
			return
		}
	}
	if index := strings.Contains(i.ZYFS, "3"); index {
		var bdate2 *time.Time
		bdate2, err = base.GetBackDATE("shls")
		if err != nil {
			return
		}
		if i.DSDT.Unix() < bdate2.Unix() {
			err = fmt.Errorf("分户日期不能小于最早可追溯日期，最大追溯日期为【" + bdate.Format("2006-01-02") + "】")
			return
		}
		//创建内存表
		sqlstr := fmt.Sprintf(`CREATE TABLE "TMP_LSCK"(
			"ACID" int,
			"DSTY" int,
			"EMID" int,
			"DSVL" decimal(8,4),
			"DSDT" date,
			"WODT" date,
			"ISWO" int,
			"DSEM" varchar(20),
			"WOEM" varchar(20)
		)%s`, eng)
		err = tx.Exec(sqlstr).Error
		if err != nil {
			return
		}
		//插入个人存款业绩转移(未终止)
		sqlstr = `INSERT INTO "TMP_LSCK"("ACID","DSTY","EMID","DSVL","DSDT","WODT","ISWO","DSEM","WOEM")
		SELECT "ACID","DSTY",? "EMID","DSVL","DSDT","WODT","ISWO",'YJZY' "DSEM","WOEM" FROM "T_INDI_ACCO_DIVI" WHERE "EMID"=? AND "ISWO"=0 AND ("WODT" IS NULL OR "WODT">?)`
		err = tx.Exec(sqlstr, i.NEMID, i.YEMID, i.DSDT).Error
		if err != nil {
			tx.Rollback()
			return
		}
		//终止认定
		sqlstr = `UPDATE "T_INDI_ACCO_DIVI" SET "WODT"=?,"WOEM"='YJZY',"ISWO"=CASE WHEN "DSDT"<? THEN 0 ELSE 1 END
		WHERE "EMID"=? AND "ISWO"=0 AND ("WODT" IS NULL OR "WODT">?)`
		err = tx.Exec(sqlstr, i.DSDT, i.DSDT, i.YEMID, i.DSDT).Error
		if err != nil {
			tx.Rollback()
			return
		}
		//插入认定
		sqlstr = `INSERT INTO "T_INDI_ACCO_DIVI"("ACID","DSTY","EMID","DSVL","DSDT","DSEM","WODT","WOEM","ISWO")
		SELECT "ACID","DSTY","EMID","DSVL",
				CASE WHEN "DSDT"<? THEN ? ELSE "DSDT" END "DSDT",
				"DSEM","WODT","WOEM","ISWO"
		FROM "TMP_LSCK"
		WHERE "DSDT"<"WODT" OR "WODT" IS NULL`
		err = tx.Exec(sqlstr, i.DSDT, i.DSDT).Error
		if err != nil {
			tx.Rollback()
			return
		}
	}
	if index := strings.Contains(i.ZYFS, "4"); index {
		//创建内存表
		sqlstr := fmt.Sprintf(`CREATE TABLE "TMP_GRDK"(
			"ACID" int,
			"DSTY" int,
			"EMID" int,
			"DSVL" decimal(8,4),
			"DSDT" date,
			"WODT" date,
			"ISWO" int,
			"DSEM" varchar(20),
			"WOEM" varchar(20)
		)%s`, eng)
		err = tx.Exec(sqlstr).Error
		if err != nil {
			return
		}
		//插入个人存款业绩转移(未终止)
		sqlstr = `INSERT INTO TMP_GRDK("ACID","DSTY","EMID","DSVL","DSDT","WODT","ISWO","DSEM","WOEM")
		SELECT "ACID","DSTY",? "EMID","DSVL","DSDT","WODT","ISWO",'YJZY' "DSEM","WOEM" FROM "T_INDI_LOAN_DIVI" WHERE "EMID"=? AND "ISWO"=0 AND ("WODT" IS NULL OR "WODT">?)`
		err = tx.Exec(sqlstr, i.NEMID, i.YEMID, i.DSDT).Error
		if err != nil {
			tx.Rollback()
			return
		}
		//终止认定
		sqlstr = `UPDATE "T_INDI_LOAN_DIVI" SET "WODT"=?,"WOEM"='YJZY',"ISWO"=CASE WHEN "DSDT"<? THEN 0 ELSE 1 END
		WHERE "EMID"=? AND "ISWO"=0 AND ("WODT" IS NULL OR "WODT">?)`
		err = tx.Exec(sqlstr, i.DSDT, i.DSDT, i.YEMID, i.DSDT).Error
		if err != nil {
			tx.Rollback()
			return
		}
		//插入认定
		sqlstr = `INSERT INTO "T_INDI_LOAN_DIVI"("ACID","DSTY","EMID","DSVL","DSDT","DSEM","WODT","WOEM","ISWO")
		SELECT "ACID","DSTY","EMID","DSVL",
				CASE WHEN "DSDT"<? THEN ? ELSE "DSDT" END "DSDT",
				"DSEM","WODT","WOEM","ISWO"
		FROM "TMP_GRDK"
		WHERE "DSDT"<"WODT" OR "WODT" IS NULL`
		err = tx.Exec(sqlstr, i.DSDT, i.DSDT).Error
		if err != nil {
			tx.Rollback()
			return
		}
	}
	return
}

func (i *UserChangeDivi) AfterSave(tx *gorm.DB) (err error) {
	if strings.Contains(i.ZYFS, "1") || strings.Contains(i.ZYFS, "2") {
		sqlstr := `DROP TABLE "TMP_DGCDK"`
		err = tx.Exec(sqlstr).Error
		if err != nil {
			tx.Rollback()
			return
		}
	}
	if index := strings.Contains(i.ZYFS, "3"); index {
		sqlstr := `DROP TABLE "TMP_LSCK"`
		err = tx.Exec(sqlstr).Error
		if err != nil {
			tx.Rollback()
			return
		}
	}
	if index := strings.Contains(i.ZYFS, "4"); index {
		sqlstr := `DROP TABLE "TMP_GRDK"`
		err = tx.Exec(sqlstr).Error
		if err != nil {
			tx.Rollback()
			return
		}
	}
	return
}

func (m *UserChangeDivi) AfterFind(tx *gorm.DB) (err error) {
	if m.ZYFS != "" {
		ids := strings.Split(m.ZYFS, ",")
		sql := `SELECT "NAME" FROM (select 1 "ID",'对公存款业绩' "NAME" UNION ALL SELECT 2 ,'对公贷款业绩' UNION ALL SELECT 3 ,'个人存款业绩' UNION ALL SELECT 4 ,'个人贷款业绩') A WHERE "ID" IN (?)`
		rows, err := base.MYDB.Raw(sql, ids).Rows()
		if err != nil {
			return err
		}
		var buff bytes.Buffer
		defer rows.Close()
		for rows.Next() {
			var caption string
			rows.Scan(&caption)
			buff.WriteString(caption)
			buff.WriteString(",")
		}
		if l := buff.Len(); l > 0 {
			buff.Truncate(l - 1)
		}
		m.ZYFSCaptions = buff.String()
	}
	return
}

func UserChangeDiviEF() base.EntityFunc {
	return func() interface{} {
		entity := UserChangeDivi{}
		return &entity
	}
}
func UserChangeDiviESF() base.EntitiesFunc {
	return func() interface{} {
		var entities []UserChangeDivi
		return &entities
	}
}

func init() {
	relationship := []string{"User", "User1"}
	base.DaoPoolObj.Put("UserChangeDivi", base.NewDefaultDao(UserChangeDiviEF(), UserChangeDiviESF(), relationship, "my"))
}
